/** \file HeapMgr.cc
 * Definitions for the class HeapMgr.
 *
 * (c) Copyright  Semih Cemiloglu
 * All rights reserved, see COPYRIGHT file for details.
 *
 * $Id: HeapMgr.cc 119 2006-06-21 04:57:25Z semihc $
 *
 *
 */

#include "HeapMgr.hh"
#include <iostream>
#include "Heap.hh"
#include "Debug.hh"


using namespace std;
using namespace TC;


TC_IDENT("$Id$");


Heap* HeapMgr::DefaultHeap()
{
  //! General purpose, default heap
  static Heap DHeap;
  
  return &DHeap;
}


Heap*& HeapMgr::CurrentHeap()
{
  static Heap* TheHeap = DefaultHeap();

  return TheHeap;
}


Heap* HeapMgr::SetCurrentHeap(Heap* h)
{
  Heap* oldHeap = GetCurrentHeap();
  CurrentHeap() = h;
  return oldHeap;
}


Heap* HeapMgr::WhichHeap(void* /*ptr*/)
{
  //TODO: Should we handle 0 value?
  return GetCurrentHeap();
}


// Substitute for the default new handler.
// See TC++PL book page 129.
void TC_new_handler()
{
  cerr << "operator new failed to get memory" << endl;
  throw std::bad_alloc();
}


/**
 * Global redefinitions for various operator new() and delete()s.
 * Note that it is important not to override the "placement" new
 * [ie., operator new(size_t, void*) ] and delete since they don't
 * involve memory management operations. Consequently, we should 
 * be using C++ implementation's version.
 */

#if TC_REDEFINE_GLOBAL_NEW

void * operator new(size_t size) throw(std::bad_alloc)
{
  return HeapMgr::GetCurrentHeap()->newMem(size, Heap::e_Scalar);
}

void * operator new[](size_t size) throw(std::bad_alloc)
{
  return HeapMgr::GetCurrentHeap()->newMem(size, Heap::e_Array);
}

void* operator new(size_t size, const std::nothrow_t&) throw()
{
  void* memptr = 0;

  try {
    memptr = HeapMgr::GetCurrentHeap()->newMem(size, Heap::e_Scalar);
  } 
  catch(...) {
  }

  return memptr;
}

void* operator new[](size_t size, const std::nothrow_t&) throw()
{
  void* memptr = 0;

  try {
    memptr = HeapMgr::GetCurrentHeap()->newMem(size, Heap::e_Array);
  } 
  catch(...) {
  }

  return memptr;
}

void operator delete(void *ptr) throw()
{
  Heap* h = HeapMgr::WhichHeap(ptr);
  if(h)
    h->deleteMem(ptr, Heap::e_Scalar);
  else
    Throw("Cannot find the heap in delete()");
    
}

void operator delete[](void *ptr) throw()
{
  Heap* h = HeapMgr::WhichHeap(ptr);
  if(h)
    h->deleteMem(ptr, Heap::e_Array);
  else
    Throw("Cannot find the heap in delete[]()");
}

#endif /* TC_REDEFINE_GLOBAL_NEW */

